home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / HippoDraw / HippoDrawSrc1.1 / Hippo.subproj / InspectAxes.m < prev    next >
Encoding:
Text File  |  1992-04-25  |  22.8 KB  |  872 lines

  1. /* InspectAxes.m        by Paul Kunz    December 1991
  2.  * Controls the Axes of a Plot object
  3.  *
  4.  * Copyright (C)  1991  The Board of Trustees of
  5.  * The Leland Stanford Junior University.  All Rights Reserved.
  6.  */
  7.  
  8. #import "InspectAxes.h"
  9.  
  10. const char InspectAxes_h_rcsid[] = INSPECTAXES_H_ID;
  11. const char InspectAxes_m_rcsid[] = "$Id: InspectAxes.m,v 1.15 1992/04/05 18:19:44 pfkeb Rel $";
  12.  
  13. #import <appkit/Application.h>
  14. #import <appkit/Button.h>
  15. #import <appkit/ButtonCell.h>
  16. #import <appkit/Form.h>
  17. #import <appkit/Matrix.h>
  18. #import <appkit/SavePanel.h>
  19.  
  20. #import "DrawDocument.h"
  21. #import "FineSlider.h"
  22. #import "HDraw.h"
  23. #import "HGraphicView.h"
  24. #import "Plot.h"
  25. #import "NewInspector.h"
  26.  
  27. #import <c.h>
  28. #import <string.h>
  29. #import <float.h>
  30.  /*
  31.   * bug fix: FLT_MIN=1.17549435e-38 is actually 0
  32.   */
  33. #undef FLT_MIN
  34. #define FLT_MIN 2e-38f
  35.  
  36. #define RB_HIGH 0
  37. #define RB_LOW 1
  38. #define RB_NUM 2
  39. #define RB_OFF 3
  40.  
  41. #define MAXBINS 500
  42.  
  43. #define OFF 0
  44. #define ON  1
  45.  
  46. #define SCALE_FACTOR 5.0
  47.  
  48. @implementation InspectAxes
  49.  
  50. - initInspFor:aDraw
  51. {
  52.     int        i, count;
  53.     
  54.     [super initInspFor:aDraw];
  55.     
  56.     [NXApp loadNibSection:"InspectAxes.nib" owner:self
  57.            withNames:NO fromZone:[self zone]];
  58.  /*
  59.   * we've got to do the following nonsense because can't stretch out spacing
  60.   * of slider from IB 
  61.   */
  62.     rbXSlider[0] = rbXSlider0;
  63.     rbXSlider[1] = rbXSlider1;
  64.     rbXSlider[2] = rbXSlider2;
  65.     rbXSlider[3] = rbXSlider3;
  66.     rbYSlider[0] = rbYSlider0;
  67.     rbYSlider[1] = rbYSlider1;
  68.     rbYSlider[2] = rbYSlider2;
  69.     rbYSlider[3] = rbYSlider3;
  70.   /*
  71.    * set the scaleFactor for FineSlider
  72.    */
  73.     count = [rbXForm cellCount];
  74.     for ( i = 0; i <= count; i++ ) {
  75.         [rbXSlider[i] setScaleFactor:SCALE_FACTOR];
  76.     }
  77.     count = [rbYForm cellCount];
  78.     for ( i = 0; i < count; i++ ) {
  79.         [rbYSlider[i] setScaleFactor:SCALE_FACTOR];
  80.     }
  81.     numLimitCheck = [limitCheckButton state];
  82.   /*
  83.    * set up one of the display options in the display options box
  84.    */
  85.  
  86.    [theInspector addView:[contentBox contentView]
  87.                  withName:"Axes Selection" withSupervisor:self];
  88.  
  89.     currentDim = 1;
  90.     return self;
  91. }
  92. - limitCheckType:sender
  93. {
  94.     numLimitCheck = [limitCheckButton state];
  95.     return self;
  96. }
  97. - (int) limitCheck:(int) nbins against:(int)maxbins
  98. {
  99.     int        irc;
  100.     static int prevnbins=0;
  101.         
  102.     if ( numLimitCheck == OFF )  return nbins;
  103.     
  104.     if ( nbins > maxbins && numLimitCheck == ON ) {
  105.         if (nbins == prevnbins) { 
  106.             nbins = maxbins;
  107.         return nbins;     /* ignore double events */
  108.         }
  109.     prevnbins = nbins;
  110.     irc = NXRunAlertPanel( "Alert",
  111.             "Greater than %d bins may cause performace problems",
  112.             "Cancel", "Proceed", NULL, maxbins );
  113.     if ( irc == NX_ALERTDEFAULT ) {
  114.         nbins = maxbins;
  115.     } else {
  116.         numLimitCheck = OFF;
  117.         [ limitCheckButton setState: OFF ];
  118.     }
  119.     }
  120.     return nbins;
  121. }
  122.  
  123.  
  124. - rebinForm:sender
  125. {
  126.     NXPoint             p;
  127.     float               thigh, tlow, toff, range;
  128.     int                 sel, tnbins;
  129.     BOOL                 re_displayX = NO;
  130.     BOOL                 re_displayY = NO;
  131.     BOOL                logAxis, checkBins;
  132.     display             adisplay = [firstPlot histDisplay];
  133.  
  134.     sel = [rbXForm selectedIndex];
  135.  
  136.     logAxis = h_getLogAxis(adisplay, XAXIS);
  137.     checkBins = graphtype == HISTOGRAM || graphtype == LEGOPLOT
  138.      || graphtype == COLORPLOT;
  139.  
  140.     if (checkBins) {
  141.     tnbins = [rbXForm intValueAt:RB_NUM];
  142.     tnbins = MAX(tnbins, 2);
  143.     tnbins = [self limitCheck:tnbins against:MAXBINS];
  144.     } else
  145.     tnbins = 50;
  146.  
  147.     thigh = [rbXForm floatValueAt:RB_HIGH];
  148.     tlow = [rbXForm floatValueAt:RB_LOW];
  149.  
  150.     if (logAxis && tlow <= 0.0)
  151.     tlow = 2 * FLT_MIN;
  152.  
  153.     if (tlow >= thigh) {
  154.     if (checkBins)
  155.         thigh = tlow + xw;
  156.     else
  157.         thigh = tlow * (1.0 + 2.0 * FLT_EPSILON);
  158.     }
  159.     range = thigh - tlow;
  160.     xw = range / tnbins;
  161.  
  162.     if ((xh != thigh) || (sel == RB_HIGH)) {
  163.     re_displayX = YES;
  164.     xh = thigh;
  165.     [rbXForm setFloatValue:xh at:RB_HIGH];
  166.     [rbXSlider[RB_HIGH] setMinValue:(double)(tlow + xw)];
  167.     [rbXSlider[RB_HIGH] setMaxValue:(double)(thigh + range)];
  168.     [rbXSlider[RB_HIGH] setFloatValue:xh];
  169.     }
  170.     if ((xl != tlow) || (sel == RB_LOW)) {
  171.     re_displayX = YES;
  172.     xl = tlow;
  173.     [rbXForm setFloatValue:xl at:RB_LOW];
  174.     if (logAxis) {
  175.         if (tlow <= range) {
  176.         [rbXSlider[RB_LOW] setMinValue:(double)tlow / 10.0];
  177.         [rbXSlider[RB_LOW] setMaxValue:(double)tlow * 10.0];
  178.         } else {
  179.         [rbXSlider[RB_LOW] setMinValue:(double)(tlow - range)];
  180.         [rbXSlider[RB_LOW] setMaxValue:(double)(thigh - xw)];
  181.         }
  182.  
  183.     } else {
  184.         [rbXSlider[RB_LOW] setMinValue:(double)(tlow - range)];
  185.         [rbXSlider[RB_LOW] setMaxValue:(double)(thigh - xw)];
  186.     }
  187.     [rbXSlider[RB_LOW] setFloatValue:xl];
  188.     }
  189.     if ((tnbins != nx) || (sel == RB_NUM)) {
  190.     if (checkBins) {
  191.         re_displayX = YES;
  192.         nx = tnbins;
  193.         [rbXForm setIntValue:nx at:RB_NUM];
  194.         [rbXSlider[RB_NUM] setMinValue:2.];
  195.         [rbXSlider[RB_NUM] setMaxValue:(double)(2 * nx)];
  196.         [rbXSlider[RB_NUM] setIntValue:nx];
  197.     }
  198.     }
  199.     toff = [rbXForm floatValueAt:RB_OFF];
  200.     if (toff != xoff) {
  201.     re_displayX = YES;
  202.     toff = MIN(toff, 1.0);
  203.     toff = MAX(toff, -1.0);
  204.     xh -= xoff * xw;
  205.     xl -= xoff * xw;
  206.     xoff = toff;
  207.     xh += xoff * xw;
  208.     xl += xoff * xw;
  209.     [rbXForm setFloatValue:xoff at:RB_OFF];
  210.     [rbXSlider[RB_OFF] setFloatValue:xoff];
  211.     [rbXForm setFloatValue:xh at:RB_HIGH];
  212.     [rbXForm setFloatValue:xl at:RB_LOW];
  213.     [rbXSlider[RB_HIGH] setFloatValue:xh];
  214.     [rbXSlider[RB_LOW] setFloatValue:xl];
  215.     }
  216.     if ( re_displayX == YES ) {
  217.     [graphicView graphicsPerform:@selector(setNumBinsForAxisX:)
  218.                 with:(id)&nx andDraw:NO];
  219.     p.x = xl;
  220.     p.y = xh;
  221.     [graphicView graphicsPerform:@selector(setRangeForAxisX:)
  222.                 with:(id)&p andDraw:YES];
  223.     [autoScaleXbutton setState:NO];
  224.     if (currentDim == 1 && [autoScaleYbutton state] == YES) {
  225.         [self rebinAutoYRange];
  226.     }
  227.     }
  228.     sel = [rbYForm selectedIndex];
  229.  
  230.     checkBins = graphtype == LEGOPLOT || graphtype == COLORPLOT;
  231.     logAxis = h_getLogAxis(adisplay, YAXIS);
  232.  
  233.     if (checkBins) {
  234.     tnbins = [rbYForm intValueAt:RB_NUM];
  235.     tnbins = MAX(tnbins, 2);
  236.     tnbins = [self limitCheck:tnbins against:MAXBINS];
  237.     } else {
  238.     tnbins = 50;
  239.     }
  240.  
  241.     thigh = [rbYForm floatValueAt:RB_HIGH];
  242.     tlow = [rbYForm floatValueAt:RB_LOW];
  243.  
  244.     if (logAxis && tlow <= 0.0)
  245.     tlow = 2 * FLT_MIN;
  246.  
  247.     if (tlow >= thigh) {
  248.     if (checkBins)
  249.         thigh = tlow + yw;
  250.     else
  251.         thigh = tlow * (1.0 + 2.0 * FLT_EPSILON);
  252.     }
  253.     range = thigh - tlow;
  254.     yw = range / tnbins;
  255.  
  256.     if ((yh != thigh) || (sel == RB_HIGH)) {
  257.     re_displayY = YES;
  258.     if ( yh != thigh ) {
  259.         [autoScaleYbutton setState:NO];
  260.     }
  261.     yh = thigh;
  262.     [rbYForm setFloatValue:yh at:RB_HIGH];
  263.     [rbYSlider[RB_HIGH] setMinValue:(double)(tlow + yw)];
  264.     [rbYSlider[RB_HIGH] setMaxValue:(double)(yh + range)];
  265.     [rbYSlider[RB_HIGH] setFloatValue:yh];
  266.     }
  267.     if ((yl != tlow) || (sel == RB_LOW)) {
  268.     re_displayY = YES;
  269.     if ( yl != tlow ) {
  270.         [autoScaleYbutton setState:NO];
  271.     }
  272.     yl = tlow;
  273.     [rbYForm setFloatValue:yl at:RB_LOW];
  274.     if (logAxis) {
  275.         if (tlow <= range) {
  276.         [rbYSlider[RB_LOW]
  277.          setMinValue:(double)tlow / 10.0];
  278.         [rbYSlider[RB_LOW]
  279.          setMaxValue:(double)tlow * 10.0];
  280.         } else {
  281.         [rbYSlider[RB_LOW] setMinValue:(double)(tlow - range)];
  282.         [rbYSlider[RB_LOW] setMaxValue:(double)(thigh - yw)];
  283.         }
  284.     } else {
  285.         [rbXSlider[RB_LOW] setMinValue:(double)(tlow - range)];
  286.         [rbXSlider[RB_LOW] setMaxValue:(double)(thigh - yw)];
  287.     }
  288.     [rbYSlider[RB_LOW] setFloatValue:yl];
  289.     }
  290.     if ((ny != tnbins) || (sel == RB_NUM)) {
  291.     if (checkBins) {
  292.         re_displayY = YES;
  293.         if ( ny != tnbins ) {
  294.         [autoScaleYbutton setState:NO];
  295.         }
  296.         ny = tnbins;
  297.         [rbYForm setIntValue:ny at:RB_NUM];
  298.         [rbYSlider[RB_NUM] setMinValue:2.];
  299.         [rbYSlider[RB_NUM] setMaxValue:(double)(2 * ny)];
  300.         [rbYSlider[RB_NUM] setIntValue:ny];
  301.     }
  302.     }
  303.     toff = [rbYForm floatValueAt:RB_OFF];
  304.     if (toff != yoff) {
  305.     re_displayY = YES;
  306.     toff = MIN(toff, 1.0);
  307.     toff = MAX(toff, -1.0);
  308.     yh -= yoff * yw;
  309.     yl -= yoff * yw;
  310.     if ( yoff != toff ) {
  311.         [autoScaleYbutton setState:NO];
  312.     }
  313.     yoff = toff;
  314.     yh += yoff * yw;
  315.     yl += yoff * yw;
  316.     [rbYForm setFloatValue:yoff at:RB_OFF];
  317.     [rbYSlider[RB_OFF] setFloatValue:yoff];
  318.     [rbYForm setFloatValue:yh at:RB_HIGH];
  319.     [rbYForm setFloatValue:yl at:RB_LOW];
  320.     [rbYSlider[RB_HIGH] setFloatValue:yh];
  321.     [rbYSlider[RB_LOW] setFloatValue:yl];
  322.     }
  323.     if ( re_displayY == YES ) {
  324.     [graphicView graphicsPerform:@selector(setNumBinsForAxisY:)
  325.                 with:(id)&ny andDraw:NO];
  326.     p.x = yl;
  327.     p.y = yh;
  328.     [graphicView graphicsPerform:@selector(setRangeForAxisY:)
  329.                 with:(id)&p andDraw:YES];
  330.     }
  331.     [[[graphicView window] flushWindow] makeKeyWindow];
  332.     return self;
  333. }
  334. - rebin:sender
  335. {
  336.      NXPoint p;
  337.      float x, y, toff, txl, txh, tyl, tyh, delta, deltaoff;
  338.      float xplo, xphi, yplo, yphi;
  339.      int                     i;
  340.      int                     slider_index;
  341.      BOOL                 re_displayX = NO;
  342.      BOOL                 re_displayY = NO;
  343.      BOOL logAxis, checkBins;
  344.      display adisplay = [firstPlot histDisplay];
  345.      BOOL zpmode;
  346.      
  347.      /*
  348.       * following are used to skip processing of multiple 
  349.       * interrupts with values unchanged
  350.       */
  351.      static int        prevXIndex = -1, prevYIndex = -1;
  352.      static float    prevXValue = 999.999, prevYValue = 999.999;
  353.      
  354.      slider_index = -1;
  355.      for (i = 0; i < 4; i++) {
  356.       if (sender == rbYSlider[i]) {
  357.            slider_index = i;
  358.            break;
  359.       }
  360.      }
  361.  
  362.      y = [sender floatValue];
  363.      h_getRange(adisplay, YAXIS, &yplo, &yphi );
  364.      zpmode = [zpYbutton state];
  365.      if  ( (i < 4) && ((slider_index != prevYIndex) || (y != prevYValue))) {
  366.  
  367.       prevYIndex = slider_index;
  368.       prevYValue = y;
  369.  
  370.       checkBins = graphtype == LEGOPLOT || graphtype == COLORPLOT;
  371.       logAxis = h_getLogAxis(adisplay, YAXIS);
  372.       
  373.       switch (slider_index) {
  374.       case RB_HIGH:
  375.            if (logAxis && y<=0.0) y = 2*FLT_MIN;
  376.            if (checkBins)
  377.            {
  378.             tyh = MAX(y, yl + 2 * yw);
  379.             delta = tyh - yh;
  380.             if (ABS(delta) > yw)
  381.             {
  382.              i = (delta > 0) ? delta / yw : delta / yw + 1;
  383.              ny = ny + i;
  384.              if ( zpmode ) ny = ny + i;
  385.              ny = [self limitCheck:ny against: MAXBINS ];
  386.              yh = yh + i * yw;
  387.              if ( zpmode ) yl = yl - i*yw;
  388.              yh = MAX(yh, yl + yw);
  389.              re_displayY = YES;
  390.             }
  391.            }
  392.            else 
  393.            {
  394.             yh = MAX(y,yl*(1.0+2.0*FLT_EPSILON));
  395.             if (zpmode) yl = yplo - (yh - yphi);
  396.             re_displayY = YES;
  397.            }
  398.            if (re_displayY)
  399.            {
  400.             [rbYForm setFloatValue:yh at:RB_HIGH];
  401.             if (checkBins) {
  402.              [rbYForm setIntValue:ny at:RB_NUM];
  403.              [rbYSlider[RB_NUM] setIntValue:ny];
  404.             }
  405.            }
  406.            break;
  407.       case RB_LOW:
  408.            if (logAxis && y<=0.0) y = 2*FLT_MIN;
  409.            if (checkBins)
  410.            {
  411.             tyl = MIN(y, yh - 2 * yw);
  412.             delta = yl - tyl;
  413.             if (ABS(delta) > yw) {
  414.              i = delta / yw;
  415.              if ( !zpmode ) {
  416.                  ny = ny + i;
  417.                  ny = [self limitCheck:ny against: MAXBINS ];
  418.              }
  419.              yl = yl - i * yw;
  420.              if (zpmode) yh = yh - i*yw;
  421.              yl = MIN(yl, yh - yw);
  422.              re_displayY = YES;
  423.             }
  424.            }
  425.            else
  426.            {
  427.             yl = MIN(y,yh*(1.0-2.0*FLT_EPSILON));
  428.             if ( zpmode ) yh = yphi + ( yl - yplo );
  429.             re_displayY = YES;
  430.            }
  431.            if (re_displayY)
  432.            {
  433.             [rbYForm setFloatValue:yl at:RB_LOW];
  434.             if (checkBins) {
  435.              [rbYForm setIntValue:ny at:RB_NUM];
  436.              [rbYSlider[RB_NUM] setIntValue:ny];
  437.             }
  438.            }
  439.            break;
  440.       case RB_NUM:
  441.            if (checkBins)
  442.            {
  443.             ny = [rbYSlider[RB_NUM] intValue];
  444.             ny = [self limitCheck:ny against: MAXBINS ];
  445.             [rbYForm setIntValue:ny at:RB_NUM];
  446.             re_displayY = YES;
  447.            }
  448.            break;
  449.       case RB_OFF:
  450.            toff = y;        /* slider value */
  451.            deltaoff = toff - yoff; /* diff from previous value of slider */
  452.            yl = yl + yw * deltaoff; /* adjust low by difference */
  453.            yh = yh + yw * deltaoff; /* adjust high by same difference */
  454.            yoff = toff;           /* set previous value = current value */
  455.            [rbYForm setFloatValue:yh at:RB_HIGH];
  456.            [rbYSlider[RB_HIGH] setFloatValue:yh];
  457.            [rbYForm setFloatValue:yl at:RB_LOW];
  458.            [rbYSlider[RB_LOW] setFloatValue:yl];
  459.            [rbYForm setFloatValue:yoff at:RB_OFF];
  460.            re_displayY = YES;
  461.            break;
  462.       }    /* end switch ySlider */
  463.       if (re_displayY == YES) {
  464.            [graphicView
  465.        graphicsPerform:@selector(setNumBinsForAxisY:)
  466.         with :(id)&ny andDraw:NO];
  467.            p.x = yl;
  468.            p.y = yh;
  469.            [graphicView graphicsPerform:@selector(setRangeForAxisY:)
  470.         with :(id)&p andDraw:YES];
  471.            if (zpmode) {
  472.                if ( slider_index == 0 ) {
  473.                [rbYForm setFloatValue:yl at:1];
  474.                [rbYSlider[1] setFloatValue:yl];
  475.            } else if ( slider_index == 1 ) {
  476.                [rbYForm setFloatValue:yh at:0];
  477.                [rbYSlider[0] setFloatValue:yh];
  478.            }
  479.            }
  480.            [ autoScaleYbutton setState:NO];
  481.            yw = (yh - yl) / (ny);
  482.       }
  483.      }
  484.  
  485.      slider_index = -1;
  486.      for (i = 0; i < 4; i++) {
  487.       if (sender == rbXSlider[i]) {
  488.            slider_index = i;
  489.            break;
  490.       }
  491.      }
  492.  
  493.      x = [sender floatValue];
  494.      h_getRange(adisplay, XAXIS, &xplo, &xphi );
  495.      zpmode = [zpXbutton state];
  496.      if  (( i < 4) && ((slider_index != prevXIndex) || (x != prevXValue))) {
  497.       prevXIndex = slider_index;
  498.       prevXValue = x;
  499.  
  500.       logAxis = h_getLogAxis(adisplay, XAXIS);
  501.       checkBins = graphtype == HISTOGRAM || graphtype == LEGOPLOT
  502.            || graphtype == COLORPLOT;
  503.       
  504.       switch (slider_index) {
  505.       case RB_HIGH:
  506.            if (logAxis && x<=0.0) x = 2*FLT_MIN;
  507.            if (checkBins)
  508.            {
  509.             txh = MAX(x, xl + 2 * xw);
  510.             delta = txh - xh;
  511.             if (ABS(delta) > xw) {
  512.              i = (delta > 0) ? delta / xw : delta / xw + 1;
  513.              nx = nx + i;
  514.              if (zpmode) nx = nx + i;
  515.              nx = [self limitCheck:nx against: MAXBINS ];
  516.              xh = xh + i * xw;
  517.              if (zpmode) xl = xl - i*xw;
  518.              xh = MAX(xh, xl + xw);
  519.              re_displayX = YES;
  520.             }
  521.            }
  522.            else
  523.            {
  524.             xh = MAX(x,xl*(1.0+2.0*FLT_EPSILON));
  525.             re_displayX = YES;
  526.             if (zpmode ) {
  527.             xl = xplo - (xh - xphi);
  528.             }
  529.            }
  530.            if (re_displayX)
  531.            {
  532.             [rbXForm setFloatValue:xh at:RB_HIGH];
  533.             [rbXForm setIntValue:nx at:RB_NUM];
  534.             [rbXSlider[RB_NUM] setIntValue:nx];
  535.            }
  536.            break;
  537.       case RB_LOW:
  538.            if (logAxis && x<=0.0) x = 2*FLT_MIN;
  539.            if (checkBins)
  540.            {
  541.             txl = MIN(x, xh - 2 * xw);
  542.             delta = xl - txl;
  543.             if (ABS(delta) > xw) {
  544.              i = delta / xw;
  545.              if (!zpmode) {
  546.                  nx = nx + i;
  547.                  nx = [self limitCheck:nx against: MAXBINS ];
  548.              }
  549.              xl = xl - i * xw;
  550.              if (zpmode) xh = xh - i * xw;
  551.              xl = MIN(xl, xh - xw);
  552.              re_displayX = YES;
  553.             }
  554.            }
  555.            else
  556.            {
  557.             xl = MIN(x,xh*(1.0-2.0*FLT_EPSILON));
  558.             if ( zpmode ) xh = xphi + ( xl - xplo );
  559.             re_displayX = YES;
  560.            }
  561.            if (re_displayX)
  562.            {
  563.             [rbXForm setFloatValue:xl at:RB_LOW];
  564.             [rbXForm setIntValue:nx at:RB_NUM];
  565.             [rbXSlider[RB_NUM] setIntValue:nx];
  566.            }
  567.            break;
  568.       case RB_NUM:
  569.            if (checkBins)
  570.            {
  571.             nx = [rbXSlider[RB_NUM] intValue];
  572.             nx = [self limitCheck:nx against: MAXBINS ];
  573.             [rbXForm setIntValue:nx at:RB_NUM];
  574.             re_displayX = YES;
  575.            }
  576.            break;
  577.       case RB_OFF:
  578.            toff = x;        /* slider value */
  579.            deltaoff = toff - xoff; /* diff from previous value of slider */
  580.            xl = xl + xw * deltaoff;/* adjust low by difference */
  581.            xh = xh + xw * deltaoff;/* adjust high by same difference */
  582.            xoff = toff;          /* set previous value = current value */
  583.            [rbXForm setFloatValue:xh at:RB_HIGH];
  584.            [rbXSlider[RB_HIGH] setFloatValue:xh];
  585.            [rbXForm setFloatValue:xl at:RB_LOW];
  586.            [rbXSlider[RB_LOW] setFloatValue:xl];
  587.            [rbXForm setFloatValue:xoff at:RB_OFF];
  588.            re_displayX = YES;
  589.            break;
  590.       }    /* end switch xSlider */
  591.       if (re_displayX == YES)
  592.       {
  593.            [graphicView graphicsPerform:@selector(setNumBinsForAxisX:)
  594.         with :(id)&nx andDraw:NO];
  595.            p.x = xl;
  596.            p.y = xh;
  597.            [graphicView graphicsPerform:@selector(setRangeForAxisX:)
  598.         with :(id)&p andDraw:YES];
  599.            if (zpmode) {
  600.                if ( slider_index == 0 ) {
  601.                [rbXForm setFloatValue:xl at:1];
  602.                [rbXSlider[1] setFloatValue:xl];
  603.            } else if ( slider_index == 1 ) {
  604.                [rbXForm setFloatValue:xh at:0];
  605.                [rbXSlider[0] setFloatValue:xh];
  606.            }
  607.            }
  608.            [ autoScaleXbutton setState: NO];
  609.            xw = (xh - xl) / (nx);
  610.            if ( currentDim == 1 &&
  611.            [autoScaleYbutton state] == YES ) {
  612.             [self rebinAutoYRange ];
  613.            }
  614.       }
  615.      }
  616.      if ((re_displayX == YES) || (re_displayY == YES)) {
  617.       [[[graphicView window] flushWindow] makeKeyWindow];
  618.      }
  619.      return self;
  620. }
  621.  
  622. - rebinAutoYRange
  623. {
  624.     NXPoint    p;
  625.         float    yrange;
  626.     
  627.         ny = [firstPlot numBinsForAxis:YAXIS];
  628.         [ firstPlot getRangeForAxisY: &p ];
  629.         yl = p.x;
  630.         yh = p.y;
  631.         yrange = yh - yl;
  632.         yw = (yh - yl) / (ny);
  633.     [rbYForm setFloatValue:yh at:RB_HIGH];
  634.        [rbYSlider[RB_HIGH] setMinValue:(double) (yl + yw)];
  635.         [rbYSlider[RB_HIGH] setMaxValue:(double) (yh + yrange)];
  636.         [rbYSlider[RB_HIGH] setFloatValue:yh];
  637.  
  638.     [rbYForm setFloatValue:yl at:RB_LOW];
  639.         [rbYSlider[RB_LOW]  setMinValue:(double) (yl - yrange)];
  640.        [rbYSlider[RB_LOW]  setMaxValue:(double) (yh - yw)];
  641.         [rbYSlider[RB_LOW]  setFloatValue:yl];
  642.     
  643.         return self;
  644.     
  645. }        
  646.  /* called when the AutoScale or logScale button is clicked */
  647. - tupleSetScaleType:sender
  648. {
  649.     SEL        theMethod = 0;
  650.     int        theState;
  651.     
  652.     theState = [sender state];
  653.     
  654.     switch ([sender tag])
  655.     {
  656.         case 0: /* AutoScale X-axis */
  657.             theMethod = @selector(setAutoScaleX:);
  658.             break;
  659.             
  660.         case 1: /* AutoScale Y-axis */
  661.             theMethod = @selector(setAutoScaleY:);
  662.             break;
  663.             
  664.         case 2: /* Log Scale X-axis */
  665.             theMethod = @selector(setLogScaleX:);
  666.             break;
  667.             
  668.         case 3: /* LogScale Y-axis */
  669.             theMethod = @selector(setLogScaleY:);
  670.             break;
  671.     }
  672.     
  673.     [graphicView graphicsPerform:theMethod
  674.         with :(id)&theState andDraw:YES];
  675.  
  676.     [self setSliders]; /* reset axis slider & form */
  677.     [[graphicView window] flushWindow];
  678.     
  679.     return self;
  680. }
  681.     
  682.  /* Methods supporting updating the Inspector View */
  683. - updateView
  684. {
  685.     if ( !firstPlot ) {
  686.         return self;
  687.     }
  688.     [ self setOptions];
  689.     [ self setSliders];
  690.     return self;
  691. }
  692. - setOptions
  693. {
  694.     display             adisplay = [firstPlot histDisplay];
  695.  
  696.     graphtype = h_getDispType(adisplay);
  697.     if (graphtype == HISTOGRAM)
  698.      currentDim = 1;
  699.     else
  700.      currentDim = 2;
  701.  
  702.     if ( (graphtype == HISTOGRAM) || ( graphtype == COLORPLOT ) ) {
  703.     [logScaleXbutton setEnabled:NO];
  704.     } else {
  705.     [logScaleXbutton setEnabled:YES];
  706.     }
  707.     if ( graphtype == COLORPLOT ) {
  708.         [logScaleYbutton setEnabled:NO];
  709.     } else {
  710.         [logScaleYbutton setEnabled:YES];
  711.     }
  712.     [autoScaleXbutton setState:h_getAutoScale(adisplay, XAXIS)];
  713.     [autoScaleYbutton setState:h_getAutoScale(adisplay, YAXIS)];
  714.     [logScaleXbutton  setState:h_getLogAxis(adisplay, XAXIS)];
  715.     [logScaleYbutton  setState:h_getLogAxis(adisplay, YAXIS)];
  716.  
  717.     return self;
  718. }
  719. - setSliders
  720. {
  721.      float               xrange, yrange;
  722.      BOOL logAxis, checkBins;
  723.      display adisplay = [firstPlot histDisplay];
  724.      
  725.      /*
  726.       * Y Axis
  727.       */
  728.      checkBins = graphtype == LEGOPLOT || graphtype == COLORPLOT;
  729.      logAxis = h_getLogAxis(adisplay, YAXIS);
  730.      
  731.      if (checkBins)
  732.      {
  733.       ny = [firstPlot numBinsForAxis:YAXIS];
  734.       [rbYForm setIntValue:ny at: RB_NUM];
  735.       [rbYSlider[RB_NUM] setMinValue:2.];
  736.       [rbYSlider[RB_NUM] setMaxValue:(double)(2 * ny)];
  737.       [rbYSlider[RB_NUM] setIntValue:ny];
  738.       [rbYSlider[RB_NUM] setEnabled:YES];
  739.       [[rbYForm cellAt:RB_NUM :0] setEnabled:YES];
  740.      }
  741.      else
  742.      {
  743.       [rbYForm setStringValue:"" at:RB_NUM];
  744.       [rbYSlider[RB_NUM] setEnabled:NO];
  745.       [[rbYForm cellAt:RB_NUM :0] setEnabled:NO];
  746.       ny = 50;
  747.      }
  748.      
  749.      [firstPlot getRangeForAxis:YAXIS low: &yl high: &yh ];
  750.      yrange = yh - yl;
  751.      yw = (yh - yl) / (ny);
  752.      [rbYForm setFloatValue:yh at:RB_HIGH];
  753.  
  754.      [rbYSlider[RB_HIGH] setMinValue:(double) (yl + yw)];
  755.      [rbYSlider[RB_HIGH] setMaxValue:(double) (yh + yrange)];
  756.      [rbYSlider[RB_HIGH] setFloatValue:yh];
  757.      
  758.      [rbYForm setFloatValue:yl at:RB_LOW];
  759.      if (logAxis)
  760.      {
  761.       if (yl <= yrange)
  762.       {
  763.            [rbYSlider[RB_LOW] setMinValue:(double) yl/10.0];
  764.            [rbYSlider[RB_LOW]  setMaxValue:(double) yl*10.0];
  765.       }
  766.       else
  767.       {
  768.            [rbYSlider[RB_LOW] setMinValue:(double) (yl - yrange)];
  769.            [rbYSlider[RB_LOW]  setMaxValue:(double) (yh - yw)];
  770.       }
  771.      }
  772.      else
  773.      {
  774.       [rbYSlider[RB_LOW]  setMinValue:(double) (yl - yrange)];
  775.       [rbYSlider[RB_LOW]  setMaxValue:(double) (yh - yw)];
  776.      }
  777.      [rbYSlider[RB_LOW]  setFloatValue:yl];
  778.      
  779.      if (checkBins)
  780.      {
  781.       [rbYForm setFloatValue:0. at:RB_OFF ];
  782.       [rbYSlider[RB_OFF] setMinValue:-1.];
  783.       [rbYSlider[RB_OFF] setMaxValue: 1.];
  784.       [rbYSlider[RB_OFF] setFloatValue: 0.];
  785.       [rbYSlider[RB_OFF] setEnabled:YES];
  786.       [[rbYForm cellAt:RB_OFF :0] setEnabled:YES];
  787.      }
  788.      else
  789.      {
  790.       [rbYForm setStringValue:"" at:RB_OFF];
  791.       [rbYSlider[RB_OFF] setEnabled:NO];
  792.       [[rbYForm cellAt:RB_OFF :0] setEnabled:NO];
  793.      }
  794.      yoff = 0.0;
  795.       
  796.      /*
  797.       * X axis
  798.       */
  799.      logAxis = h_getLogAxis(adisplay, XAXIS);
  800.      checkBins = graphtype == LEGOPLOT || graphtype == HISTOGRAM
  801.       || graphtype == COLORPLOT;
  802.  
  803.      if (checkBins)
  804.      {
  805.       nx = [firstPlot numBinsForAxis:XAXIS];
  806.       [rbXForm setIntValue:nx at: RB_NUM];
  807.       [rbXSlider[RB_NUM] setMinValue:2.];
  808.       [rbXSlider[RB_NUM] setMaxValue:(double)(2 * nx)];
  809.       [rbXSlider[RB_NUM] setIntValue:nx];
  810.       [rbXSlider[RB_NUM] setEnabled:YES];
  811.       [[rbXForm cellAt:RB_NUM :0] setEnabled:YES];
  812.      }
  813.      else
  814.      {
  815.       [rbXForm setStringValue:"" at:RB_NUM];
  816.       [rbXSlider[RB_NUM] setEnabled:NO];
  817.       [[rbXForm cellAt:RB_NUM :0] setEnabled:NO];
  818.       nx = 50;
  819.      }
  820.       
  821.      [firstPlot getRangeForAxis:XAXIS low: &xl high: &xh ];
  822.      xrange = xh - xl;
  823.      xw = (xh - xl) / (nx);
  824.      [rbXForm setFloatValue:xh at:RB_HIGH];
  825.      [rbXSlider[RB_HIGH] setMinValue:(double) (xl + xw)];
  826.      [rbXSlider[RB_HIGH] setMaxValue:(double) (xh + xrange)];
  827.      [rbXSlider[RB_HIGH] setFloatValue:xh];
  828.      
  829.      [rbXForm setFloatValue:xl at:RB_LOW];
  830.      if (logAxis)
  831.      {
  832.       if (xl <= xrange)
  833.       {
  834.            [rbXSlider[RB_LOW] setMinValue:(double) xl/10.0];
  835.            [rbXSlider[RB_LOW]  setMaxValue:(double) xl*10.0];
  836.       }
  837.       else
  838.       {
  839.            [rbXSlider[RB_LOW]  setMaxValue:(double) (xh - xw)];
  840.            [rbXSlider[RB_LOW] setMinValue:(double) (xl - xrange)];
  841.       }
  842.      }
  843.      else
  844.      {
  845.       [rbXSlider[RB_LOW]  setMinValue:(double) (xl - xrange)];
  846.       [rbXSlider[RB_LOW]  setMaxValue:(double) (xh - xw)];
  847.      }
  848.      [rbXSlider[RB_LOW]  setMaxValue:(double) (xh - xw)];
  849.      [rbXSlider[RB_LOW]  setFloatValue:xl];
  850.      
  851.      if (checkBins)
  852.      {
  853.       [rbXForm setFloatValue:0. at:RB_OFF ];
  854.       [rbXSlider[RB_OFF] setMinValue:-1.];
  855.       [rbXSlider[RB_OFF] setMaxValue: 1.];
  856.       [rbXSlider[RB_OFF] setFloatValue: 0.];
  857.       [rbXSlider[RB_OFF] setEnabled:YES];
  858.       [[rbXForm cellAt:RB_OFF :0] setEnabled:YES];
  859.      }
  860.      else
  861.      {
  862.       [rbXForm setStringValue:"" at:RB_OFF];
  863.       [rbXSlider[RB_OFF] setEnabled:NO];
  864.       [[rbXForm cellAt:RB_OFF :0] setEnabled:NO];
  865.      }
  866.      xoff = 0.0;
  867.  
  868.      return self;
  869. }
  870.  
  871. @end
  872.